﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase.Protocol;
using SuperSocket.SocketBase;
using DeviceControlServer.ServerBase;
using DeviceCommon;
using LogLib;

namespace DeviceControlServer
{
    /// <summary>
    ///  代表监听客户端连接，承载TCP连接的服务器实例。
    ///  理想情况下，我们可以通过AppServer实例获取任何你想要的客户端连接，
    ///  服务器级别的操作和逻辑应该定义在此类之中。       
    /// </summary>
    public class DeviceServer : AppServer<ClientRequestPackSession, BinaryRequestInfo>, IServer
    {
        protected string _error = "";
        public string ErrorMessage
        {
            get
            {
                return _error;
            }
        }

        /// <summary>
        /// 指示服务器是否已经启动
        /// </summary>
        public bool Running
        {
            get { return this.State == ServerState.Running; }
        }

        //缓冲字节数组
        private byte[] buffer = new byte[2048];
   
        public Dictionary<string, IDevice> Devices
        {
            get;
            set;
        }

        /// <summary>
        /// 当前活动的会话
        /// </summary>
        public ClientRequestPackSession ActivedSession
        {
            get;
            set;
        }

        /// <summary>
        /// 当前活动的设备
        /// </summary>
        public IDevice ActivedDevice
        {
            get;
            set;
        }

        /// <summary>
        /// 初始化失败的设备列表
        /// </summary>
        private List<KeyValuePair<string, string>> listInitFailedDevices = new List<KeyValuePair<string, string>>();

        /// <summary>
        /// 存储session和对应ip端口号的泛型集合
        /// </summary>
        public Dictionary<string, ClientRequestPackSession> SessionList = new Dictionary<string, ClientRequestPackSession>();

        public event DeviceStateChangedEventHandler StateChanged;
        public void OnDeviceStateChanged(IDevice dev, DeviceState state, string message)
        {
            if (StateChanged != null)
            {
                StateChanged(this, new DeviceStateChangedEventArgs(dev, state, message));
            }
        }

        public event DeviceMsgResponsedEventHandler MsgResponsed;
        public void ReportDeviceReponse(ResponseMsgPackge packge)
        {
            if (MsgResponsed != null)
            {
                MsgResponsed(this, new DeviceMsgResponsedEventArgs(packge));
            }
        }

        public event DeviceActionTimeoutEventHandler ActionTimeout;
        public void OnActionTimeout(string message)
        {
            if (ActionTimeout != null)
            {
                ActionTimeout(this, new DeviceActionTimeoutEventArgs(message));
            }
        }

        public event Action AppExited;
        public void OnAppExited(string inParams)
        {
            if (AppExited != null)
            {
                AppExited();
            }
        }

        private LocalServerConfig _config = new LocalServerConfig();

        public DeviceServer()
            : base(new ClientRequestPackReceiveFilterFactory())
        {
            
        }

        public event NewSessionRequestReceivedHandler NewSessionRequestReceived;
        public void OnNewSessionRequestReceived(ClientRequestPackSession session, RequestMsgPackge pack)
        {
            ActivedSession = session;
            if (NewSessionRequestReceived != null)
            {
                NewSessionRequestReceived(session, pack);
            }
        }

        public bool Init()
        {
            var config = new SuperSocket.SocketBase.Config.ServerConfig()
            {
                Name = _config.Name,
                ServerTypeName = _config.Name,
                ClearIdleSession = _config.ClearIdleSession, // 300秒执行一次清理300秒没数据传送的连接
                ClearIdleSessionInterval = _config.ClearIdleSessionInterval,
                IdleSessionTimeOut = _config.IdleSessionTimeOut,
                MaxRequestLength = _config.MaxRequestLength, //最大包长度
                Ip = _config.Ip,
                Port = _config.Port,
                MaxConnectionNumber = _config.MaxConnectionNumber,
            };
            
            if (this.State == ServerState.NotInitialized)
            {
                if (Setup(config))
                {
                    string info = string.Format("{0}初始化成功, IP:{1}, port:{2}", _config.Name, _config.Ip, _config.Port);
                    Log.WriteAsync(info);
                    return true;
                }
                else
                {
                    _error = "Failed to Setup:" + _config.Name;
                    Log.WriteAsync(_error);
                    return false;
                }
            }
            return true;
        }

        public bool StartServer()
        {
            if (this.State == ServerState.Running)
            {
                return true;
            }
            if (this.State == ServerState.NotStarted)
            {
                if (Start())
                {
                    return true;
                }
                else
                {
                    _error = "Failed to Start";
                    return false;
                }
            }
            return true;    
        }

        public override void Stop()
        {
            if (Running)
            {
                base.Stop();
            }
        }

        public void Close()
        {
            if (Running)
            {
                base.Stop();               
            }
            this.Dispose();
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="session"></param>
        /// <param name="requestInfo"></param>
        private void appServer_NewRequestReceived(ClientRequestPackSession session, BinaryRequestInfo requestInfo)
        {         
            //ActivedSession = session;
            //session.Charset = Encoding.UTF8;
            //ipAddress_Receive = session.RemoteEndPoint.ToString();
            //SetMessage("收到" + ipAddress_Receive + "数据: " + requestInfo.Key + " " + requestInfo.Body);
        }

        public void InitDevices(string inParamString)
        {
            listInitFailedDevices.Clear();
            foreach (KeyValuePair<string, IDevice> p in Devices)
            {             
                string outParams = "";
                IDevice device = p.Value;
                device.Init(inParamString, out outParams);
                if (!device.Inited)
                {
                    string info = string.Format("{0}初始化失败: {1}", device.Name, device.ErrorMessage);
                    Log.WriteAsync(info);
                    OnInitFailed(device, device.ErrorMessage, "");
                    listInitFailedDevices.Add(new KeyValuePair<string, string>(device.Name, device.ErrorMessage));
                }
                else
                {
                    OnInitOK(device, "");
                }
            }
        }

        protected void OnInitOK(IDevice device, string outParams = "")
        {
            ResponseMsgPackge pack = new ResponseMsgPackge(device.Name, DeviceAction.Init);
            pack.Success = true;
            pack.ActionState = DeviceActionState.InitOK;
            pack.Message = "";
            pack.SetParams(outParams);
            ReportDeviceReponse(pack);
        }

        protected void OnInitFailed(IDevice device, string reasonMsg, string outParams)
        {
            ResponseMsgPackge pack = new ResponseMsgPackge(device.Name, DeviceAction.Init);
            pack.Success = false;
            pack.ActionState = DeviceActionState.InitFailed;
            pack.Message = reasonMsg;
            pack.SetParams(outParams);
            ReportDeviceReponse(pack);
        }

        public void DisposeDevices(string inParamString)
        {
            foreach (KeyValuePair<string, IDevice> p in Devices)
            {
                string outParams = "";
                IDevice device = p.Value;
                if (device != null && device.Inited)
                {
                    device.Exit(inParamString, out outParams);
                }
                if (device.State != DeviceState.NotInitialized)
                {
                    //info = "卸载设备失败: " + device.ErrorMessage;
                    //TakeLog(p.Key + info);
                }
            }
        }

        /// <summary>
        /// 检查初始化结果
        /// </summary>
        /// <returns></returns>
        public bool CheckInitResult(out string msg)
        {
            msg = "";
            if (listInitFailedDevices.Count > 0)
            {
                StringBuilder builder = new StringBuilder();               
                for (int i = 0; i < listInitFailedDevices.Count; i++)
                {
                    builder.Append(listInitFailedDevices[i].Key);
                    builder.Append(":");
                    builder.Append(listInitFailedDevices[i].Value);
                }
                msg = builder.ToString();
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 当观测超时
        /// </summary>
        /// <param name="action"></param>
        /// <param name="msg"></param>
        public void OnWatchTimeout(ClientRequestPackSession session, IDevice device, string action, string msg)
        {
            ResponseMsgPackge pack = new ResponseMsgPackge(device.Name, action);
            pack.Success = false;
            pack.Message = msg;
            pack.ActionState = DeviceActionState.Timeout;
            ReportDeviceReponse(pack);
            session.Send(pack);
        }

        public void OnCatchException(ClientRequestPackSession session, IDevice device, string action, Exception ex)
        {
            ResponseMsgPackge pack = new ResponseMsgPackge(device.Name, action);
            pack.Success = false;
            pack.Message = ex.Message;
            pack.ActionState = DeviceActionState.CatchException;
            pack.SetParams("");
            ReportDeviceReponse(pack);
            session.Send(pack);
        }

        public void SendPackage(ResponseMsgPackge pack)
        {
            if(ActivedSession != null)
            {
                ActivedSession.Send(pack);
            }
        }
    }
}
